package com.boodaba.todocarts.test.domain;

import static com.googlecode.instinct.expect.Expect.expect;

import java.util.ArrayList;
import java.util.List;

import org.jmock.Expectations;
import org.junit.runner.RunWith;

import com.boodaba.todocarts.domain.Label;
import com.boodaba.todocarts.domain.LabelIdSpecification;
import com.boodaba.todocarts.domain.LabelRepository;
import com.boodaba.todocarts.infstr.IStoreContext;
import com.googlecode.instinct.integrate.junit4.InstinctRunner;
import com.googlecode.instinct.marker.annotate.BeforeSpecification;
import com.googlecode.instinct.marker.annotate.Mock;
import com.googlecode.instinct.marker.annotate.Specification;
import com.googlecode.instinct.marker.annotate.Stub;
import com.googlecode.instinct.marker.annotate.Subject;

@RunWith(InstinctRunner.class)
public class LabelRepositoryShould {
	@Subject private LabelRepository SUT;
	
	@Mock private IStoreContext mStoreContext;
		
	@Stub Label mLabel1;
	@Stub Label mLabel2;
	@Stub Label mLabel3;
	@Stub Label mLabel4;
	@Stub Label mLabel5;
	@Stub Label mLabel6;
	
	@BeforeSpecification
	public void setUp() {
		SUT = new LabelRepository(mStoreContext);
		mLabel1 = new Label("label 1");
		mLabel2 = new Label("label 2");
		mLabel3 = new Label("label 3");
		mLabel4 = new Label("label 4");
		mLabel5 = new Label("label 1");
		mLabel6 = new Label("label 6");
	}
	
	@Specification
	void returnAllOfStoredLabels() {
		expect.that(new Expectations() {{
			List<Label> allLabels = getAll();
			oneOf(mStoreContext).allOf(Label.class); will(returnValue(allLabels));
		}});
		List<Label> labelList = SUT.findAll();
		expect.that(labelList.size() == 4).isTrue();
	}
	
	@Specification
	void getSingleOrNonLabelByTitle() {
		expect.that(new Expectations() {{
			oneOf(mStoreContext).getBySpecification(with(any(LabelIdSpecification.class)));
				will(returnValue(mLabel2));
			oneOf(mStoreContext).getBySpecification(with(any(LabelIdSpecification.class)));
				will(returnValue(null));
		}});
		Label l1 = SUT.getLabelByTitle("label 2");
		Label l2 = SUT.getLabelByTitle("label 5");
		expect.that(l1.identicalTo(mLabel2)).isTrue();
		expect.that(l2 == null).isTrue();
	}
	
	@Specification
	void shouldSaveLabel() {
		expect.that(new Expectations() {{
			oneOf(mStoreContext)
			.bindBySpecification(with(same(mLabel6)), with(any(LabelIdSpecification.class)));
			oneOf(mStoreContext).save(mLabel6);
			oneOf(mStoreContext).commit();
		}});
		SUT.save(mLabel6);
	}
	
	@Specification
	void shouldDeleteLabel() {
		expect.that(new Expectations() {{
			oneOf(mStoreContext)
			.bindBySpecification(with(same(mLabel3)), with(any(LabelIdSpecification.class)));
			oneOf(mStoreContext).delete(mLabel3);
			oneOf(mStoreContext).commit();
		}});
		SUT.delete(mLabel3);
	}
	
	private List<Label> getAll() {
		List<Label> rL = new ArrayList<Label>();
		rL.add(mLabel1);
		rL.add(mLabel2);
		rL.add(mLabel3);
		rL.add(mLabel4);
		
		return rL;
	}
	
}
